home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
MATHS
/
RLAB
/
RLAB125.ZIP
/
!RLaB
/
misc
/
plplot
< prev
next >
Wrap
Text File
|
1996-04-09
|
58KB
|
2,618 lines
#
# New plot.r for use with PLPLOT library.
# The help files for these functions are in
# misc/plhelp
#
# plplot.r
# This file is a part of RLaB ("Our"-LaB)
# Copyright (C) 1994 Ian R. Searle
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# See the file ../COPYING
#
# If your system does not deal with Infs and NaNs well, then
# uncomment the following lines.
#
# static (isinf, isnan)
#
# isinf = function ( A ) { return (0); };
# isnan = function ( A ) { return (0); };
static (WIN) # The static plot window structure
static (P) # The active/current plot window
#
# Maintain the transformations for 3-D plots.
#
static (basex, basey, height)
basex = 2;
basey = 2;
height = 4;
#
# Static (private) functions. For use from within
# this file only.
#
static (create_plot_object)
static (check_plot_object)
static (xy_scales)
static (x_scales)
static (y_scales)
static (z_scales)
static (XYZ_scales)
static (list_scales)
static (list_sort)
static (hist_scales)
static (plot_matrix)
static (plot_list)
static (check_3d_list)
static (find_char)
static (get_style)
static (make_legend)
static (plhold_first)
#
# Defaults
#
static (grid_x_default, grid_y_default)
static (grid_3x_default, grid_3y_default, grid_3z_default)
grid_x_default = "bcnst";
grid_y_default = "bcnstv";
grid_3x_default = "bnstu";
grid_3y_default = "bnstu";
grid_3z_default = "bcdmnstuv";
static (subplot_f)
subplot_f = 0;
#
# Create the default plot-object.
# Initialize to all the default values
#
if (!exist (WIN))
{
# Create the plot-object list
WIN = <<>>;
}
create_plot_object = function ( N, nx, ny )
{
if (!exist (N)) { N = 0; }
pobj = <<>>;
pobj.subplot = 0; # The current subplot no.
pobj.nplot = nx*ny; # Total no. of plots on window
pobj.fontld = 0; # Loaded extended fonts?
for (i in 1:(nx*ny))
{
pobj.style.[i] = "line"; # The type/style of plot to draw
pobj.nbin[i] = 1j; # The number of bins for a histogram
pobj.width[i] = 1; # The pen width for current plot
pobj.font[i] = 1; # The current font
pobj.xlabel[i] = "";
pobj.ylabel[i] = "";
pobj.zlabel[i] = "";
pobj.title[i] = "";
pobj.orientation[i] = "portrait";
pobj.desc.[i] = "default"; # The legend description
pobj.gridx[i] = grid_x_default; # Plot axes style, 2D-X
pobj.gridy[i] = grid_y_default; # Plot axes style, 2D-Y
pobj.grid3x[i] = grid_3x_default; # Plot axes style, 3D-X
pobj.grid3y[i] = grid_3y_default; # Plot axes style, 3D-Y
pobj.grid3z[i] = grid_3z_default; # Plot axes style, 3D-Z
pobj.aspect[i] = 0; # Plot aspect style
pobj.alt[i] = 60;
pobj.az[i] = 45;
pobj.xmin[i] = 1j;
pobj.xmax[i] = 1j;
pobj.ymin[i] = 1j;
pobj.ymax[i] = 1j;
pobj.zmin[i] = 1j;
pobj.zmax[i] = 1j;
pobj.page.xp = 0;
pobj.page.yp = 0;
pobj.xleng = 400;
pobj.yleng = 300;
pobj.xoff = 200;
pobj.yoff = 200;
pobj.color[i;] = 1:14; # 14 possible colors...
pobj.lstyle[i;] = 1:8; # 8 possible line styles...
pobj.pstyle[i;] = 1:8; # 8 possible point styles...
}
#
# Save the newly generated plot-object
# in a list of plot-objects.
WIN.[N] = pobj;
};
##############################################################################
#
# Check to make sure a plot-object exists. If one
# does not exist, create it.
#
check_plot_object = function ()
{
if (length (WIN) == 0)
{
plstart();
return 0;
}
return 1;
};
##############################################################################
#
# Set the current plot window
# Default value = 0
#
plwin = function ( N )
{
check_plot_object ();
if (!exist (N)) { N = 0; }
# Check to make sure N is valid
for (i in members (WIN))
{
if (N == strtod (i))
{
_plsstrm (N);
return P = N;
}
}
printf ("plwin: invalid argument, N = %i\n", N);
printf (" valid values are:\n");
WIN?
};
##############################################################################
#
# Show the current plot-window, and the possibilities
#
showplwin = function ( all )
{
if (length (WIN) == 0)
{
printf ("No plot objects\n");
return 0;
}
printf ("Current plot-window is:\t\t%i\n", P);
printf ("Available plot windows are:\t");
for (i in members (WIN))
{
printf ("%s ", i);
}
printf ("\n");
if (exist (all))
{
for (i in members (WIN.[P]))
{
WIN.[P].[i]
}
}
};
getplot = function ( win_no )
{
local (win_no)
if (length (WIN) != 0)
{
if (!exist (win_no)) { win_no = P; }
if (exist (WIN.[win_no]))
{
return (WIN.[win_no]);
else
return 0;
}
}
return <<>>;
};
##############################################################################
#
# Set the plot-window orientation (portrait, landscape, rotated).
#
plsori = function ( rot )
{
_plsori (rot);
};
##############################################################################
#
# Set/start/select the plot device
#
plstart = function ( nx, ny, dev )
{
if (!exist (nx)) { nx = 1; }
if (!exist (ny)) { ny = 1; }
if (!exist (dev)) { dev = "?"; }
# Create the plot-object
# First, figure out the index
if (!exist (P))
{
P = 0;
else
P = P + 1;
}
create_plot_object (P, nx, ny);
_plsstrm (P);
#_plscolbg (255,255,255); # white
# Default window size for X
_plspage (0, 0, 400, 300, 200, 200);
# Start up the plot-window
_plstart (dev, nx, ny);
_plwid (8);
# Turn between plot pause off
_plspause (0);
_pltext ();
return P;
};
##############################################################################
#
# Close a plot device. We must destroy the current plot-object
# And switch the output stream back to the default.
#
plclose = function ()
{
if (size (WIN) > 1)
{
#
# Clear WIN.[P] and reset P to 1st plot-window
#
clear (WIN.[P]);
_plend1 ();
_plsstrm (strtod (members (WIN)[1]));
P = strtod (members (WIN)[1]);
return P;
else if (size (WIN) == 1) {
if (exist (WIN.[P]))
{
clear (WIN.[P]);
clear (P);
}
_plend1 ();
return 1;
else if (size (WIN) == 0) {
return 0;
} } }
};
##############################################################################
#
# Close ALL the plot-windows
#
plend = function ()
{
_plend ();
if (exist (WIN)) { clear (WIN); }
if (exist (P)) { clear (P); }
WIN = <<>>;
};
##############################################################################
#
# Change plot aspect ratio
#
plaspect = function ( aspect )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (!exist (aspect))
{
WIN.[P].aspect[i] = 0;
else
WIN.[P].aspect[i] = aspect;
}
};
##############################################################################
#
# Change plot line style
#
plstyle = function ( style )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (style))
{
if (class (style) == "string")
{
for (j in 1:style.n)
{
if (style[j] != "line" && ...
style[j] != "point" && ...
style[j] != "line-point")
{
error ("plstyle: STYLE must be either " + ...
"\"point\", \"line\" or \"line-point\"");
}
}
WIN.[P].style.[i] = style;
}
return 1;
}
WIN.[P].style.[i] = "line";
return 1;
};
##############################################################################
#
# Control of the plot line style.
# There are 8 line styles
plline = function ( line_style )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (line_style))
{
if (class (line_style) == "num")
{
if (line_style.nc != 8)
{
error ("plpoint: LVEC must be 1x8 in size");
}
WIN.[P].lstyle[i;] = line_style;
}
return 1;
}
WIN.[P].lstyle[i;] = 1:8;
return 1;
};
##############################################################################
#
# Control of the plot point style.
# There are 8 line styles
plpoint = function ( point_style )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (point_style))
{
if (class (point_style) == "num")
{
if (point_style.nc != 8)
{
error ("plpoint: PVEC must be 1x8 in size");
}
WIN.[P].pstyle[i;] = point_style;
}
return 1;
}
WIN.[P].pstyle[i;] = 1:8;
return 1;
};
##############################################################################
#
# Get the right value of line-style
#
get_style = function ( STY, K )
{
local (sty);
sty = mod(K, STY.n);
if(sty == 0)
{
sty = STY.n;
}
return STY[sty];
};
##############################################################################
#
# Change fonts
#
plfont = function ( font )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (!exist (font)) { font = 1; }
if (WIN.[P].fontld == 0)
{
_plfontld (1);
WIN.[P].fontld = 1;
}
WIN.[P].font[i] = font;
return P;
};
##############################################################################
#
# Change pen width
#
plwid = function ( width )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (!exist (width)) { width = 1; }
WIN.[P].width[i] = width;
return P;
};
##############################################################################
#
# Place some text on the plot
#
plptex = function ( text, x , y , dx , dy , just )
{
if (!check_plot_object ())
{
printf ("Must use plot() before plptex()\n");
return 0;
}
if (!exist (x)) { x = 0; }
if (!exist (y)) { y = 0; }
if (!exist (dx)) { dx = abs(x)+1; }
if (!exist (dy)) { dy = 0; }
if (!exist (just)) { just = 0; }
_plptex (x, y, dx, dy, just, text);
};
##############################################################################
#
# Set up the viewing altitude for 3-D plots
#
plalt = function ( ALT )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (ALT))
{
WIN.[P].alt[i] = ALT;
else
WIN.[P].alt[i] = 60;
}
return P;
};
##############################################################################
#
# Set the viewing azimuth for 3-D plots
#
plaz = function ( AZ )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (AZ))
{
WIN.[P].az[i] = AZ;
else
WIN.[P].az[i] = 45;
}
return P;
};
##############################################################################
#
# Find a character in a string
#
find_char = function ( str , char )
{
tmp = strsplt (str);
for (i in 1:tmp.n)
{
if (tmp[i] == char)
{
return i;
}
}
return 0;
};
##############################################################################
#
# Sort list element names/labels by numeric order, then string order.
#
list_sort = function ( L )
{
tl = <<>>;
j = k = 1;
for (i in members (L))
{
if (!isnan (strtod (i)))
{
num[j] = i;
j++;
else
char[k] = i;
k++;
}
}
# Sort the numeric labels
if (exist (num))
{
num = sort (strtod (num)).val;
tl.num = num;
}
if (exist (char))
{
tl.char = char;
}
return tl;
};
##############################################################################
#
# Set the subplot, this overides the action in plot().
#
subplot = function ( sub )
{
check_plot_object ();
if (!exist (sub))
{
subplot_f = 0;
_pladv (0);
else
if (sub > WIN.[P].nplot)
{
error ("Current window does not have this many subplots");
}
if (sub > 0)
{
WIN.[P].subplot = sub - 1;
subplot_f = 1;
_pladv (sub);
else
if (sub == 0)
{
# Do not advance, stay at current subplot
WIN.[P].subplot = WIN.[P].subplot - 1;
subplot_f = 1;
}
}
}
};
##############################################################################
#
# Plot the columns of a matrix (X-Y plot).
#
##############################################################################
plot = function ( data, key, textf )
{
check_plot_object ();
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
if (!exist (key)) { key = 1; }
if (!exist (textf)) { textf = 1; }
#
# Draw the graph
# Step through the matrix plotting
# each column versus the 1st
#
if (class (data) == "num")
{
#
# Set up the plot basics
#
if (abs (key) > data.nc)
{
error_1 ("plot: KEY argument > M.nc");
}
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
#
# Compute scale limits
#
k = find ((1:data.nc) != abs (key));
if (key > 0)
{
if (data.nc != 1)
{
x_scales ( real(data)[;key], p, xmin, xmax );
y_scales ( real(data)[;k], p, ymin, ymax );
else
x_scales ( (1:data.nr)', p, xmin, xmax );
y_scales ( real(data), p, ymin, ymax );
}
else if (key < 0) {
x_scales ( real(data)[;k], p, xmin, xmax );
y_scales ( real(data)[;abs(key)], p, ymin, ymax );
else
x_scales ( (1:data.nr)', p, xmin, xmax );
y_scales ( real(data), p, ymin, ymax );
} }
_plwind (xmin, xmax, ymin, ymax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
if (plot_matrix ( data, key, p, 0, xmin, xmax, ymin, ymax, ymax-ymin ) < 0)
{
return -1;
}
else if (class (data) == "list") {
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
list_scales ( data, key, p, xmin, xmax, ymin, ymax );
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
_plwind (xmin, xmax, ymin, ymax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
if (plot_list ( data, key, p, xmin, xmax, ymin, ymax ) < 0)
{
return -1;
}
else
error ("plot: un-acceptable argument");
} }
_pllsty (1);
_plcol (1);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
_plflush ();
if (textf)
{
_pltext ();
}
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
#
# plhold:
# Plot some data, and "hold" on for more.
# Plot the data, setting up the plot as usual the first time.
# On subsequent plots do not do any setup, just plot some
# more. plhold_off must be called to finish up.
#
plhold_first = 1; # True (1) if plhold() has NOT been used.
# Or if plhold_off() has been used.
# False (0) if plhold is in use
static (hxmin, hxmax, hymin, hymax)
plhold = function ( data, key )
{
check_plot_object ();
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
if (!exist (key)) { key = 1; }
if (abs (key) > data.nc)
{
error_1 ("plot: KEY argument > M.nc");
}
if (plhold_first)
{
if (class (data) == "num")
{
#
# Do the setup ONCE
#
hxmin = hxmax = hymin = hymax = 0;
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
xy_scales ( real(data), p, hxmin, hxmax, hymin, hymax );
k = find ((1:data.nc) != abs (key));
if (key > 0)
{
x_scales ( real(data)[;key], p, xmin, xmax );
if (data.nc != 1)
{
y_scales ( real(data)[;k], p, ymin, ymax );
else
y_scales ( (1:data.nr)', p, ymin, ymax );
}
else if (key < 0) {
x_scales ( real(data)[;k], p, xmin, xmax );
y_scales ( real(data)[;abs(key)], p, ymin, ymax );
else
x_scales ( (1:data.nr)', p, xmin, xmax );
y_scales ( real(data), p, ymin, ymax );
} }
_plwind (hxmin, hxmax, hymin, hymax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
else
error ("plot: un-acceptable argument");
}
plhold_first = 0;
}
if (plot_matrix ( data, key, p, 0, hxmin, hxmax, hymin, hymax, hymax-hymin ) < 0)
{
return -1;
}
_plcol (1);
_plflush ();
_pltext ();
return P;
};
##############################################################################
#
# Clean up the plotting environment and get ready
# for normal interactive usage.
#
plhold_off = function ( )
{
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
plhold_first = 1;
_plcol (1);
_plflush ();
_pltext ();
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# Plot a 3-Dimensional graph. The data is composed in a list, with
# elements `x', `y', and `z'. x and y are single-dimension arrays
# (row or column matrices), and z is a two-dimensional array. The
# array z, is a function of x and y: z = f(x,y). Thus, the values in
# the array x can be thought of a "row-labels", and the values of y
# can be thought of as "column-lables" for the 2-dimensioal array z.
#
# At present plot3 can plot 3 distinct lists. Each list may have
# different X, Y, and Z scales.
#
##############################################################################
plot3 = function ( L31, L32, L33 )
{
check_plot_object ();
#
# 1st check list contents
#
if (exist (L31)) { check_3d_list (L31); }
if (exist (L32)) { check_3d_list (L32); }
if (exist (L33)) { check_3d_list (L33); }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
#
# Figure out the scale limits.
# Needs improvement!
#
xmin = xmax = ymin = ymax = zmin = zmax = 0;
if (exist (L31))
{
XYZ_scales (L31.x, L31.y, L31.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
xmin = Xmin; xmax = Xmax;
ymin = Ymin; ymax = Ymax;
zmin = Zmin; zmax = Zmax;
}
if (exist (L32))
{
XYZ_scales (L32.x, L32.y, L32.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
}
if (exist (L33))
{
XYZ_scales (L33.x, L33.y, L33.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
}
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
# basex = 2; basey = 2; height = 4;
xmin2d = -2.0; xmax2d = 2.0;
ymin2d = -3.0; ymax2d = 5.0;
_plenv (xmin2d, xmax2d, ymin2d, ymax2d, 0, -2);
_plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
_plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
_plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
if (exist (L31))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L31.x)); else x = real (L31.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L31.y)); else y = real (L31.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L31.z)); else z = real (L31.z); }
_plcol (2);
_plot3d (x, y, z, L31.x.n, L31.y.n, 3, 0);
}
if (exist (L32))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L32.x)); else x = real (L32.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L32.y)); else y = real (L32.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L32.z)); else z = real (L32.z); }
_plcol (3);
_pllsty (2);
_plot3d (x, y, z, L32.x.n, L32.y.n, 3, 0);
}
if (exist (L33))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L33.x)); else x = real (L33.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L33.y)); else y = real (L33.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L33.z)); else z = real (L33.z); }
_plcol (4);
_pllsty (3);
_plot3d (x, y, z, L33.x.n, L33.y.n, 3, 0);
}
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# Plot a 3-Dimensional graph. The data is composed in a list, with
# elements `x', `y', and `z'. x and y are single-dimension arrays
# (row or column matrices), and z is a two-dimensional array. The
# array z, is a function of x and y: z = f(x,y). Thus, the values in
# the array x can be thought of a "row-labels", and the values of y
# can be thought of as "column-lables" for the 2-dimensioal array z.
#
# At present plmesh can plot 3 distinct lists. Each list may have
# different X, Y, and Z scales.
#
##############################################################################
plmesh = function ( L31, L32, L33 )
{
check_plot_object ();
#
# 1st check list contents
#
if (exist (L31)) { check_3d_list (L31); }
if (exist (L32)) { check_3d_list (L32); }
if (exist (L33)) { check_3d_list (L33); }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
#
# Figure out the scale limits.
# Needs improvement!
#
xmin = xmax = ymin = ymax = zmin = zmax = 0;
if (exist (L31))
{
XYZ_scales (L31.x, L31.y, L31.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
xmin = Xmin; xmax = Xmax;
ymin = Ymin; ymax = Ymax;
zmin = Zmin; zmax = Zmax;
}
if (exist (L32))
{
XYZ_scales (L32.x, L32.y, L32.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
}
if (exist (L33))
{
XYZ_scales (L33.x, L33.y, L33.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
}
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
# basex = 2; basey = 2; height = 4;
xmin2d = -2.0; xmax2d = 2.0;
ymin2d = -3.0; ymax2d = 5.0;
_plenv (xmin2d, xmax2d, ymin2d, ymax2d, 0, -2);
_plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
_plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
_plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
if (exist (L31))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L31.x)); else x = real (L31.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L31.y)); else y = real (L31.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L31.z)); else z = real (L31.z); }
_plcol (2);
_plmesh (x, y, z, L31.x.n, L31.y.n, 3);
}
if (exist (L32))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L32.x)); else x = real (L32.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L32.y)); else y = real (L32.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L32.z)); else z = real (L32.z); }
_plcol (3);
_pllsty (2);
_plmesh (x, y, z, L32.x.n, L32.y.n, 3);
}
if (exist (L33))
{
if (find_char (WIN.[P].grid3x[p], "l"))
{ x = log10 (real (L33.x)); else x = real (L33.x); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ y = log10 (real (L33.y)); else y = real (L33.y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ z = log10 (real (L33.z)); else z = real (L33.z); }
_plcol (4);
_pllsty (3);
_plmesh (x, y, z, L33.x.n, L33.y.n, 3);
}
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# Plot contours. The data is composed in a list, with
# elements `x', `y', and `z'. x and y are single-dimension arrays
# (row or column matrices), and z is a two-dimensional array. The
# array z, is a function of x and y: z = f(x,y). Thus, the values in
# the array x can be thought of a "row-labels", and the values of y
# can be thought of as "column-lables" for the 2-dimensioal array z.
#
##############################################################################
plcont = function ( CL )
{
check_plot_object ();
#
# 1st check list contents
#
if (exist (CL)) { check_3d_list (CL); }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
#
# Figure out the scale limits.
# Needs improvement!
#
xmin = xmax = ymin = ymax = zmin = zmax = 0;
if (exist (CL))
{
XYZ_scales (CL.x, CL.y, CL.z, p, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (Xmin < xmin) { xmin = Xmin; } if (Xmax > xmax) { xmax = Xmax; }
if (Ymin < ymin) { ymin = Ymin; } if (Ymax > ymax) { ymax = Ymax; }
if (Zmin < zmin) { zmin = Zmin; } if (Zmax > zmax) { zmax = Zmax; }
}
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
#
# Set up the 1st viewport for drawing the plot.
#
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
_plvpas (0.15, 0.75, 0.15, 0.85, WIN.[P].aspect[p]);
# _plvpor (0.15, 0.75, 0.15, 0.85);
_plwind (xmin, xmax, ymin, ymax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
# Convert the data to log data if necessary.
if (find_char (WIN.[P].gridx[p], "l"))
{ x = log10 (real (CL.x)); else x = real (CL.x); }
if (find_char (WIN.[P].gridy[p], "l"))
{ y = log10 (real (CL.y)); else y = real (CL.y); }
z = real (CL.z);
if (exist (CL.clevel))
{
clevel = CL.clevel;
else
clevel = linspace(zmin, zmax, 10);
}
#
# Draw the contours
#
l = 1;
for (i in 1:clevel.n)
{
k = mod (i-1, 14) + 1;
j = mod (i-1, 8) + 1;
_pllsty(j);
_plcol (1+k);
if (_plcont (x, y, z, 1, CL.x.n, 1, CL.y.n, clevel[i]))
{
llevel[l] = clevel[i];
l = l + 1;
}
}
#
# Reset color and draw the labels.
#
_plcol (1);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
#
# Draw the contour legend. Use a new viewport to the right
# of the contour plot.
#
#_plvpas (0.75, 1.0, 0.15, 0.85, WIN.[P].aspect[p]);
_plvpor (0.75, 1.0, 0.15, 0.85);
_plwind (0, 1, 0, 1);
v = 1 - 1/(2*llevel.n);
for (i in 1:llevel.n)
{
xl = [0.1, 0.2, 0.3]';
yl = [v, v, v]';
v = v - 1/llevel.n;
k = mod (i-1, 14) + 1;
j = mod (i-1, 8) + 1;
_plcol (1+k);
_pllsty (j);
_plline (3, xl, yl);
sprintf (stmp, "%.2g", llevel[i]);
plptex (stmp, xl[3]+.1, yl[3], , , 0);
}
# Flush and go back to text mode.
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# Plot 3-D lines, etc...
#
pl3d = function ( X, Y, Z, BR )
{
local (X, Y, Z, BR)
check_plot_object ();
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
#
# Some basic checks
#
if ((N = X.n) != Y.n) { error ("pl3d: X and Y must have same length"); }
if (N != Z.n) { error ("pl3d: X and Z must have same length"); }
if (!exist (BR)) { BR = N; }
if (mod (N, BR) != 0) { error ("pl3d: X.n must be divisible by BR"); }
iBR = int (N / BR);
if (iBR == 1) { k = N; else k = BR; }
#
# Figure out the scale limits.
# Needs improvement!
#
xmin = xmax = ymin = ymax = zmin = zmax = 0;
XYZ_scales (X, Y, Z, p, xmin, xmax, ymin, ymax, zmin, zmax);
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (find_char (WIN.[P].grid3x[p], "l"))
{ X = log10 (real (X)); else X = real (X); }
if (find_char (WIN.[P].grid3y[p], "l"))
{ Y = log10 (real (Y)); else Y = real (Y); }
if (find_char (WIN.[P].grid3z[p], "l"))
{ Z = log10 (real (Z)); else Z = real (Z); }
# basex = 2; basey = 2; height = 4;
xmin2d = -2.0; xmax2d = 2.0;
ymin2d = -3.0; ymax2d = 5.0;
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
_plwind (xmin2d, xmax2d, ymin2d, ymax2d);
_plw3d (basex, basey, height, xmin, xmax, ymin, ymax, ...
zmin, zmax, WIN.[P].alt[p], WIN.[P].az[p]);
_plbox3 (WIN.[P].grid3x[p], WIN.[P].xlabel[p], 0, 0, ...
WIN.[P].grid3y[p], WIN.[P].ylabel[p], 0, 0, ...
WIN.[P].grid3z[p], WIN.[P].zlabel[p], 0, 0);
_plmtex ("t", 1.0, 0.5, 0.5, WIN.[P].title[p]);
_plcol (2);
for (i in 1:iBR)
{
j = [(i-1)*k+1:i*k];
_plline3 (k, X[j], Y[j], Z[j]);
}
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# error bar plot
#
plerry = function (x, y, y_low, y_high)
{
check_plot_object ();
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
WIN.[P].desc.[p] = 1j; // use own legend
if (x.nr != y.nr || x.nr != y_low.nr || x.nr != y_high.nr)
{
error(" Size inconsistent in plerry.");
}
_plgra ();
_plcol (1);
_pllsty (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
xy_scales ( real([x,y,y_low,y_high]), p, xmin, xmax, ymin, ymax );
if (!subplot_f)
{
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
_plwind (xmin, xmax, ymin, ymax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
if (plot_matrix ( [x,y], p, 0, xmin, xmax, ymin, ymax, ymax-ymin ) < 0)
{
return -1;
}
_plcol (3);
_plerry(x.nr, x, y_low, y_high);
_plcol (1);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return P;
};
##############################################################################
#
# Plot a Histogram(s), from the columns of a matrix.
#
##############################################################################
plhist = function ( M , nbin )
{
check_plot_object ();
if (!exist (nbin)) { nbin = 10; }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
np = M.nr;
# Compute max/min values of data
ymin = min (min (real (M)));
ymax = max (max (real (M)));
#
# Check computed scale limits against user's
#
if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
_plgra ();
_plcol (1);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
for (i in 1:M.nc)
{
hscale[i] = hist_scales (M[;i], nbin);
}
if (!subplot_f) {
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
_plwind (ymin, ymax, 0, max (hscale));
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
v = max (hscale);
xmax = ymax;
for (i in 1:M.nc)
{
k = mod (i, 14) + 1;
_plcol (WIN.[P].color[p;k]);
_plhist (np, real(M[;i]), ymin, ymax, nbin, 1);
if (!any (any (WIN.[P].desc.[p] == 1j)))
{
# Use the default if necessary
if (WIN.[P].desc.[p][1] == "default")
{
desc = "c"+num2str(i);
else if (WIN.[P].desc.[p].n >= i) {
desc = WIN.[P].desc.[p][i];
else
# Not sure what to do, user has messed up.
desc = "";
} }
v = v - max(hscale)/11;
xl = (ymax-ymin)*[10.5/12, 11/12, 11.5/12]' + ymin;
yl = [v, v, v]';
_plline (3, xl, yl);
plptex(desc, xl[1]-(ymax-ymin)/25, yl[3], , , 1);
}
}
_plcol (1);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return 1;
};
##############################################################################
#
# Various support functions for the WIN list
#
##############################################################################
#
# Replot
#
replot = function ( )
{
check_plot_object ();
_replot ();
};
##############################################################################
#
# Set the X-axis label
#
xlabel = function ( xstr )
{
check_plot_object ();
if (!exist (xstr)) { xstr = ""; }
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
WIN.[P].xlabel[i] = xstr;
};
##############################################################################
#
# Set the Y-axis label
#
ylabel = function ( xstr )
{
check_plot_object ();
if (!exist (xstr)) { xstr = ""; }
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
WIN.[P].ylabel[i] = xstr;
};
##############################################################################
#
# Set the Z-axis label
#
zlabel = function ( xstr )
{
check_plot_object ();
if (!exist (xstr)) { xstr = ""; }
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
WIN.[P].zlabel[i] = xstr;
};
##############################################################################
#
# Set the plot-title
#
pltitle = function ( xstr )
{
check_plot_object ();
if (!exist (xstr)) { xstr = ""; }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
WIN.[P].title[p] = xstr;
};
##############################################################################
#
# Set the scale limits.
#
plimits = function ( xmin, xmax, ymin, ymax, zmin, zmax )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (xmin))
{
WIN.[P].xmin[i] = xmin;
else
WIN.[P].xmin[i] = 1j;
}
if (exist (xmax))
{
WIN.[P].xmax[i] = xmax;
else
WIN.[P].xmax[i] = 1j;
}
if (exist (ymin))
{
WIN.[P].ymin[i] = ymin;
else
WIN.[P].ymin[i] = 1j;
}
if (exist (ymax))
{
WIN.[P].ymax[i] = ymax;
else
WIN.[P].ymax[i] = 1j;
}
if (exist (zmin))
{
WIN.[P].zmin[i] = zmin;
else
WIN.[P].zmin[i] = 1j;
}
if (exist (zmax))
{
WIN.[P].zmax[i] = zmax;
else
WIN.[P].zmax[i] = 1j;
}
};
##############################################################################
#
# Set 2-D grid styles. A not-so-friendly interface.
#
plgrid = function ( sty_x, sty_y )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (sty_x))
{
if (class (sty_x) == "string")
{
WIN.[P].gridx[i] = sty_x;
else
error ("plgrid: requires string argument GRID_STY_X");
}
else
WIN.[P].gridx[i] = grid_x_default;
}
if (exist (sty_y))
{
if (class (sty_y) == "string")
{
WIN.[P].gridy[i] = sty_y;
else
error ("plgrid: requires string argument GRID_STY_Y");
}
else
WIN.[P].gridy[i] = grid_y_default;
}
};
##############################################################################
#
# Set 3-D grid (axis) styles
#
plgrid3 = function ( sty_x, sty_y, sty_z )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (sty_x))
{
if (class (sty_x) == "string")
{
WIN.[P].grid3x[i] = sty_x;
else
error ("plgrid3: requires string argument GRID_STY_X");
}
else
WIN.[P].grid3x[i] = grid_3x_default;
}
if (exist (sty_y))
{
if (class (sty_y) == "string")
{
WIN.[P].grid3y[i] = sty_y;
else
error ("plgrid3: requires string argument GRID_STY_Y");
}
else
WIN.[P].grid3y[i] = grid_3y_default;
}
if (exist (sty_z))
{
if (class (sty_z) == "string")
{
WIN.[P].grid3z[i] = sty_z;
else
error ("plgrid3: requires string argument GRID_STY_Z");
}
else
WIN.[P].grid3z[i] = grid_3z_default;
}
};
##############################################################################
#
# A friendlier interface to changing 2-D grid/axis
# styles.
#
plaxis = function ( X_STR, Y_STR )
{
check_plot_object ();
i = mod (WIN.[P].subplot, WIN.[P].nplot) + 1;
if (exist (X_STR))
{
if (X_STR == "log") { WIN.[P].gridx[i] = "bcngstl"; }
else
WIN.[P].gridx[i] = grid_x_default;
}
if (exist (Y_STR))
{
if (Y_STR == "log") { WIN.[P].gridy[i] = "bcngstlv"; }
else
WIN.[P].gridy[i] = grid_y_default;
}
return P;
};
##############################################################################
#
# Various internal support functions. Eventually these will be static.
#
##############################################################################
#
# Find the X or Y scale limits .
# M can be a multi-column matrix, all columns
# will be used.
#
x_scales = function ( M, p, xmin, xmax )
{
#
# 1st check for un-plottable data
#
if (any (any (isinf (M))))
{ error ("plot: cannot plot Infs"); }
if (any (any (isnan (M))))
{ error ("plot: cannot plot NaNs"); }
xmin = min (min (M));
xmax = max (max (M));
#
# Check computed scale limits against user's
#
if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
#
# Check for potential errors
#
if (xmin == xmax)
{
# As good a guess as any
xmin = xmin - 1;
xmax = xmax + 1;
}
#
# Finally, adjust if log-scales
#
if (find_char (WIN.[P].gridx[p], "l"))
{
if (xmin <= 0 || xmax <= 0) { error ("cannot plot log(x<=0)"); }
xmin = log10 (xmin);
xmax = log10 (xmax);
}
return 1;
};
y_scales = function ( M, p, xmin, xmax )
{
#
# 1st check for un-plottable data
#
if (any (any (isinf (M))))
{ error ("plot: cannot plot Infs"); }
if (any (any (isnan (M))))
{ error ("plot: cannot plot NaNs"); }
xmin = min (min (M));
xmax = max (max (M));
#
# Check computed scale limits against user's
#
if (WIN.[P].ymin[p] != 1j) { xmin = WIN.[P].ymin[p]; }
if (WIN.[P].ymax[p] != 1j) { xmax = WIN.[P].ymax[p]; }
#
# Check for potential errors
#
if (xmin == xmax)
{
# As good a guess as any
xmin = xmin - 1;
xmax = xmax + 1;
}
#
# Finally, adjust if log-scales
#
if (find_char (WIN.[P].gridy[p], "l"))
{
if (xmin <= 0 || xmax <= 0) { error ("cannot plot log(y<=0)"); }
xmin = log10 (xmin);
xmax = log10 (xmax);
}
return 1;
};
z_scales = function ( M, p, xmin, xmax )
{
#
# 1st check for un-plottable data
#
if (any (any (isinf (M))))
{ error ("plot: cannot plot Infs"); }
if (any (any (isnan (M))))
{ error ("plot: cannot plot NaNs"); }
xmin = min (min (M));
xmax = max (max (M));
#
# Check computed scale limits against user's
#
if (WIN.[P].zmin[p] != 1j) { xmin = WIN.[P].zmin[p]; }
if (WIN.[P].zmax[p] != 1j) { xmax = WIN.[P].zmax[p]; }
#
# Check for potential errors
#
if (xmin == xmax)
{
# As good a guess as any
xmin = xmin - 1;
xmax = xmax + 1;
}
#
# Finally, adjust if log-scales
#
if (find_char (WIN.[P].gridz[p], "l"))
{
if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log(z<=0)"); }
xmin = log10 (xmin);
xmax = log10 (xmax);
}
return 1;
};
##############################################################################
#
# Find the X and Y scales for a single matrix. (OLD)
#
xy_scales = function ( M, p, xmin, xmax, ymin, ymax )
{
#
# 1st check for un-plottable data
#
if (any (any (isinf (M))))
{ error ("plot: cannot plot infs"); }
if (any (any (isnan (M))))
{ error ("plot: cannot plot NaNs"); }
if (M.nc == 1)
{
xmin = 1;
xmax = M.nr;
ymin = min (M);
ymax = max (M);
else
xmin = min (M[;1]);
xmax = max (M[;1]);
ymin = min (min (M[;2:M.nc]));
ymax = max (max (M[;2:M.nc]));
}
#
# Check computed scale limits against user's
#
if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
#
# Check for potential errors
#
if (xmin == xmax)
{
xmin = xmin - 1;
xmax = xmax + 1;
}
if (ymin == ymax)
{
ymin = ymin - 1;
ymax = ymax + 1;
}
#
# Finally, adjust if log-scales
#
if (find_char (WIN.[P].gridx[p], "l"))
{
if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log <= 0"); }
xmin = log10 (xmin);
xmax = log10 (xmax);
}
if (find_char (WIN.[P].gridy[p], "l"))
{
if (ymin <= 0 || ymax <= 0) { error ("plot: cannot plot log <= 0"); }
ymin = log10 (ymin);
ymax = log10 (ymax);
}
return 1;
};
##############################################################################
#
# Find the X, Y and Z scales for a single matrix.
#
XYZ_scales = function ( X, Y, Z, p, xmin, xmax, ymin, ymax, zmin, zmax )
{
# X - scale
if (any (any (isinf (X))))
{ error ("cannot plot infs"); }
if (any (any (isnan (X))))
{ error ("cannot plot NaNs"); }
xmin = min (real (X));
xmax = max (real (X));
# Y - scale
if (any (any (isinf (Y))))
{ error ("cannot plot infs"); }
if (any (any (isnan (Y))))
{ error ("cannot plot NaNs"); }
ymin = min (real (Y));
ymax = max (real (Y));
# Z - scale
if (any (any (isinf (Y))))
{ error ("cannot plot infs"); }
if (any (any (isnan (Y))))
{ error ("cannot plot NaNs"); }
zmin = min (min (real (Z)));
zmax = max (max (real (Z)));
#
# Check computed scale limits against user's
#
if (WIN.[P].xmin[p] != 1j) { xmin = WIN.[P].xmin[p]; }
if (WIN.[P].xmax[p] != 1j) { xmax = WIN.[P].xmax[p]; }
if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
if (WIN.[P].zmin[p] != 1j) { zmin = WIN.[P].zmin[p]; }
if (WIN.[P].zmax[p] != 1j) { zmax = WIN.[P].zmax[p]; }
#
# Check for potential errors
#
if (xmin == xmax)
{
# As good a guess as any
xmin = xmin - 1;
xmax = xmax + 1;
}
if (ymin == ymax)
{
# As good a guess as any
ymin = ymin - 1;
ymax = ymax + 1;
}
if (zmin == zmax)
{
# As good a guess as any
zmin = zmin - 1;
zmax = zmax + 1;
}
#
# Finally, adjust if log-scales
#
if (find_char (WIN.[P].grid3x[p], "l"))
{
if (xmin <= 0 || xmax <= 0) { error ("plot: cannot plot log(x<=0)"); }
xmin = log10 (xmin);
xmax = log10 (xmax);
}
if (find_char (WIN.[P].grid3y[p], "l"))
{
if (ymin <= 0 || ymax <= 0) { error ("plot: cannot plot log(y<=0)"); }
ymin = log10 (ymin);
ymax = log10 (ymax);
}
if (find_char (WIN.[P].grid3z[p], "l"))
{
if (zmin <= 0 || zmax <= 0) { error ("plot: cannot plot log(z<=0)"); }
zmin = log10 (zmin);
zmax = log10 (zmax);
}
return 1;
};
##############################################################################
#
# Find the X and Y scales for a list of matrices
#
list_scales = function ( data, key, p, Xmin, Xmax, Ymin, Ymax )
{
once = 1;
for (i in members (data))
{
M = real (data.[i]);
if (class (M) != "num") { continue; }
if (abs (key) > M.nc)
{
error_1 ("plot: KEY argument > M.nc");
}
#
# 1st check for un-plottable data
#
if (any (any (isinf (M))))
{ error ("plot: cannot plot infs"); }
if (any (any (isnan (M))))
{ error ("plot: cannot plot NaNs"); }
k = find ((1:M.nc) != abs (key));
if (key > 0)
{
if (M.nc != 1)
{
x_scales ( real(M)[;key], p, xmin, xmax );
y_scales ( real(M)[;k], p, ymin, ymax );
else
x_scales ( (1:M.nr)', p, xmin, xmax );
y_scales ( real(M), p, ymin, ymax );
}
else if (key < 0) {
x_scales ( real(M)[;k], p, xmin, xmax );
y_scales ( real(M)[;abs(key)], p, ymin, ymax );
else
x_scales ( (1:M.nr)', p, xmin, xmax );
y_scales ( real(M), p, ymin, ymax );
} }
if (once)
{
Xmin = xmin; Xmax = xmax; Ymin = ymin; Ymax = ymax;
once = 0;
}
if (xmin < Xmin) { Xmin = xmin; }
if (xmax > Xmax) { Xmax = xmax; }
if (ymin < Ymin) { Ymin = ymin; }
if (ymax > Ymax) { Ymax = ymax; }
}
return 1;
};
##############################################################################
#
# Find the maximum number of elements in a bin for a single
# column matrix.
#
hist_scales = function ( data, nbin )
{
dmin = min (real (data));
dmax = max (real (data));
dbin = linspace (dmin, dmax, nbin+1);
binval = zeros (nbin, 1);
for (i in 1:nbin)
{
binval[i] = length (find (data >= dbin[i] && data < dbin[i+1]));
}
return max (binval);
};
##############################################################################
#
# Plot the columns of a matrix (core function)
#
# Notes: This is the core function for plotting a matrix. If the
# matrix is a single column, then the matrix elements are plotted
# versus the row numbers. If it is a multi-column matrix, then
# columns 2:N are plotted versus column 1.
#
# p, K, k and l are indices for plot features.
# p: the current plot index (the plot #)
# K: usually 0. This index is used to start of the line style and
# color index (k = color index, l = line-style index). This is mostly
# used by plot_list, which may call plot_matrix repeatedly.
# k: the line color index. This value determines the line color used
# for each column of data. If K = 0, then k goes like 2:14, then
# flops back to 1:14.
# l: the line style inex. This value determines the line style used
# for each column of data - not the line-type (points, or lines). If
# K = 0, then l goes like 2:8, then flops back to 1:8.
#
##############################################################################
plot_matrix = function ( M, key, p, K, xmin, xmax, ymin, ymax, v )
{
np = M.nr;
if (M.nc == 1)
{
x = 1:M.nr;
y = real (M);
k = mod (1+K, 14) + 1;
l = mod (1+K, 8);
if (find_char (WIN.[P].gridx[p], "l"))
{ x = log10 (x); }
if (find_char (WIN.[P].gridy[p], "l"))
{ y = log10 (y); }
_plcol (WIN.[P].color[p;k]);
_pllsty (WIN.[P].lstyle[p;l]);
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (M.nr, x, y);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (M.nr, x, y, WIN.[P].pstyle[p;l]);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (M.nr, x, y);
_plpoin (M.nr, x, y, WIN.[P].pstyle[p;l]);
else {
_plline (M.nr, x, y);
}}}}
#
# Now do the legend
#
if (!any (any (WIN.[P].desc.[p] == 1j)))
{
# Use the default if necessary
if (WIN.[P].desc.[p][1] == "default")
{
desc = "c1";
else if (WIN.[P].desc.[p].n >= k-1) {
desc = WIN.[P].desc.[p][k-1];
else
# Not sure what to do, user has messed up.
desc = "";
} }
v = v - (ymax-ymin)/11;
xl = (xmax-xmin)*[10.5/12, 11/12, 11.5/12]' + xmin;
yl = [v, v, v]' + ymin;
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (3, xl, yl);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (3, xl, yl, WIN.[P].pstyle[p;l]);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (3, xl, yl);
_plpoin (3, xl, yl, WIN.[P].pstyle[p;l]);
} } }
plptex(desc, xl[1]-(xmax-xmin)/25, yl[3], , , 1);
}
else
#
# Check for large column dimension
#
if (M.nc > 3*M.nr)
{
printf (" Plot %i columns and %i rows, are you sure (y/n) ? "...
, M.nc, M.nr);
ans = getline ("stdin");
if (ans.[1] != "y") { return -1; }
}
ki = find ((1:M.nc) != abs (key));
for (i in ki)
{
if (key > 0)
{
x = real (M[;key]);
y = real (M[;i]);
else if (key < 0) {
x = real (M[;i]);
y = real (M[;abs(key)]);
else
x = (1:M.nr)';
y = real (M[;i]);
} }
# Check for log scales, adjust if necessary
if (find_char (WIN.[P].gridx[p], "l"))
{ x = log10 (x); }
if (find_char (WIN.[P].gridy[p], "l"))
{ y = log10 (y); }
k = mod (i-1 + K, 14) + 1;
l = mod (8 + i-2 + K, 8) + 1;
_plcol (WIN.[P].color[p;k]);
_pllsty (WIN.[P].lstyle[p;l]);
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (np, x, y);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (np, x, y, WIN.[P].pstyle[p;l]);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (np, x, y);
_plpoin (np, x, y, WIN.[P].pstyle[p;l]);
else {
_plline (np, x, y);
}}}}
#
# Now do the legend
#
if (!any (any (WIN.[P].desc.[p] == 1j)))
{
# Use the default if necessary
if (WIN.[P].desc.[p][1] == "default")
{
desc = "c" + num2str (i);
else if (WIN.[P].desc.[p].n >= k-1) {
desc = WIN.[P].desc.[p][k-1];
else
# Not sure what to do, user has messed up.
desc = "";
}}
v = v - (ymax-ymin)/11;
xl = (xmax-xmin)*[10.5/12, 11/12, 11.5/12]' + xmin;
yl = [v, v, v]' + ymin;
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (3, xl, yl);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (3, xl, yl, WIN.[P].pstyle[p;l]);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (3, xl, yl);
_plpoin (3, xl, yl, WIN.[P].pstyle[p;l]);
}}}
plptex(desc, xl[1]-(xmax-xmin)/25, yl[3], , , 1);
}
}
}
return k-1;
};
##############################################################################
#
# Plot all of the matrices in a list on the same plot
#
plot_list = function ( L, key, p, xmin, xmax, ymin, ymax )
{
k = 0;
v = ymax - ymin;
#
# Sort out the list members
#
sl = list_sort (L);
# Plot the list members with numeric labels 1st.
if (exist (sl.num))
{
for (i in sl.num)
{
M = L.[i];
if (class (M) != "num") { continue; }
if ((k = plot_matrix (M, key, p, k, xmin, xmax, ymin, ymax, v)) < 0)
{
return k;
}
}
}
# Now plot the list members with string labels.
if (exist (sl.char))
{
for (i in sl.char)
{
M = L.[i];
if (class (M) != "num") { continue; }
if ((k = plot_matrix (M, key, p, k, xmin, xmax, ymin, ymax, v)) < 0)
{
return k;
}
}
}
return 1;
};
##############################################################################
#
# Check the elements of LIST.
# LIST must contain elements `x', `y',
# and `z'
#
check_3d_list = function ( LIST )
{
#
# Check existence and types
#
if (class (LIST) != "list") {
error ("plot3: argument must be a list");
}
if (!exist (LIST.x)) {
error ("plot3: arg must contain `x' member");
else if (class (LIST.x) != "num") {
error ("plot3: x must be numeric");
} }
if (!exist (LIST.y)) {
error ("plot3: arg must contain `y' member");
else if (class (LIST.y) != "num") {
error ("plot3: y must be numeric");
} }
if (!exist (LIST.z)) {
error ("plot3: arg must contain `z' member");
else if (class (LIST.z) != "num") {
error ("plot3: z must be numeric");
} }
#
# Check sizes
#
if (LIST.x.n != LIST.z.nr)
{
error ("plot3: x.n != z.nr");
}
if (LIST.y.n != LIST.z.nc)
{
error ("plot3: y.n != z.nc");
}
};
##############################################################################
#
# A special type of histogram plot.
#
plhistx = function ( M , nbin )
{
check_plot_object ();
if (!exist (nbin)) { nbin = 10; }
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
np = M.nr;
# Compute max/min values of data
ymin = min (min(real (M)));
ymax = max (max(real (M)));
#
# Check computed scale limits against user's
#
if (WIN.[P].ymin[p] != 1j) { ymin = WIN.[P].ymin[p]; }
if (WIN.[P].ymax[p] != 1j) { ymax = WIN.[P].ymax[p]; }
_plgra ();
_plcol (15);
_plfont (WIN.[P].font[p]);
_plwid (WIN.[P].width[p]);
dbin = (linspace (ymin, ymax, nbin+1))';
for (j in 1:M.nc)
{
// counting
for (i in 1:nbin)
{
binval[i;j] = length (find (M[;j] >= dbin[i] && M[;j] < dbin[i+1]));
}
}
if (!subplot_f) {
_pladv (0); # Advance 1 subplot
else
subplot_f = 0; # The user has set the subplot
}
if (WIN.[P].aspect[p] != 0)
{
_plvasp (WIN.[P].aspect[p]);
else
_plvsta ();
}
xmin = 0;
xmax = max(max(binval));
_plwind (ymin, ymax, xmin, xmax);
_plbox (WIN.[P].gridx[p], 0, 0, WIN.[P].gridy[p], 0, 0);
#
# Now reorganize dbin and binval so we plot points in
# the middle of the bins.
#
delbin = abs(dbin[2] - dbin[1]);
dbin = (linspace (ymin+delbin/2, ymax-delbin/2, nbin))';
dbin = [ymin ; dbin ; ymax];
binval = [zeros(1,binval.nc); binval; zeros(1,binval.nc)];
v = xmax;
for (i in 1:M.nc)
{
k = mod (i, 14) + 1;
l = mod (i, 8) + 1;
_plcol (WIN.[P].color[p;k]);
_pllsty (WIN.[P].lstyle[p;l]);
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (nbin+2, dbin, binval[;i]);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (nbin+2, dbin, binval[;i], WIN.[P].pstyle[p]+k);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (nbin+2, dbin, binval[;i]);
_plpoin (nbin+2, dbin, binval[;i], WIN.[P].pstyle[p]+k);
} } }
// write legend around upper-right corner.
// it is better to have user to choose location for legend.
if (!any (any (WIN.[P].desc.[p] == 1j)))
{
# Use the default if necessary
if (WIN.[P].desc.[p][1] == "default")
{
desc = "c"+num2str(i);
else if (WIN.[P].desc.[p].n >= i) {
desc = WIN.[P].desc.[p][i];
else
# Not sure what to do, user has messed up.
desc = "";
} }
v = v - (xmax)/11;
xt = (ymax-ymin)*[10.5/12, 11/12, 11.5/12]' + ymin;
yt = [v, v, v]';
if (get_style (WIN.[P].style.[p], k-1) == "line")
{
_plline (3, xt, yt);
else if (get_style (WIN.[P].style.[p], k-1) == "point") {
_plpoin (3, xt, yt, WIN.[P].pstyle[p]+k);
else if (get_style (WIN.[P].style.[p], k-1) == "line-point") {
_plline (3, xt, yt);
_plpoin (3, xt, yt, WIN.[P].pstyle[p]+k);
} } }
plptex(desc, xt[1]-(ymax-ymin)/25, yt[3], , , 1);
}
}
_plcol (15);
_pllab (WIN.[P].xlabel[p], WIN.[P].ylabel[p], WIN.[P].title[p]);
_plflush ();
_pltext ();
#
# Increment the plot no. so that next time
# we use the correct settings.
#
WIN.[P].subplot = WIN.[P].subplot + 1;
return 1;
};
##############################################################################
#
# Create a legend in the current plot window
#
# if pobj.desc.[p] = inf() no legend
# if pobj.desc.[p] = "default" default ("c1", "c2", ...)
# if pobj.desc.[p] = "string" use "string" as description
#
#
# Set the current plot legend string
#
plegend = function ( LEGEND )
{
check_plot_object ();
p = mod (WIN.[P].subplot, WIN.[P].nplot) + 1; # The current index
if (!exist (LEGEND))
{
WIN.[P].desc.[p] = 1j;
return P;
}
if (class (LEGEND) == "string")
{
WIN.[P].desc.[p] = LEGEND;
}
return P;
};
set3d = function (bx, by, h)
{
if (!exist (bx)) { basex = 2; else basex = bx; }
if (!exist (by)) { basey = 2; else basey = by; }
if (!exist (h)) { height = 4; else height = h; }
};